home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ultimedia 1
/
Ultimedia 1.iso
/
tools
/
sonstiges
/
easysound
/
sound.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-04
|
25KB
|
621 lines
/* Easy Sound */
/// "includes"
#include <exec/types.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include <stdio.h>
#include "EasySound.h"
#define CLOCK_CONSTANT 3579545
/* An IOAudio pointer to each sound channel: */
struct IOAudio *IOA[4] = {
NULL, NULL, NULL, NULL
};
typedef LONG Fixed;
typedef struct {
ULONG oneShotHiSamples; /* #samples in the high octave 1-shot part */
ULONG repeatHiSamples; /* #samples in the high octave repeat part */
ULONG samplesPerHiCycle; /* #samples/cycle in high octave, else 0 */
UWORD samplesPerSec; /* Data sampling rate */
UBYTE ctOctave; /* Number of octaves of waveforms */
UBYTE sCompression; /* Data compression technique used */
Fixed volume; /* Playback volume from 0 to 0x10000 */
} Voice8Header;
/* Declare the functions we are going to use: */
BOOL ESPlaySound (struct SoundInfo *info, UWORD volume, UBYTE channel,
BYTE priority, WORD delta_rate, UWORD repeat,
ULONG start, ULONG time, BOOL wait);
void ESStopSound (UBYTE channel);
BOOL ESPrepareIOA (UWORD period, UWORD volume, UWORD cycles, UBYTE channel,
BYTE priority, struct SoundInfo *info, ULONG start,
ULONG time);
void ESRemoveSound (struct SoundInfo *info);
struct SoundInfo *ESPrepareSound (STRPTR file);
UWORD ESLoadSound (STRPTR filename, struct SoundInfo *info);
ULONG ESGetSize (STRPTR filename);
ULONG ESSizeIFF (STRPTR filename);
UWORD ESReadIFF (STRPTR filename, struct SoundInfo *info);
BOOL ESMoveTo (STRPTR check_string, FILE * file_ptr);
///
/// "ESPlaySound"
/* ESPlaySound() */
/* ESPlaySound() plays one already prepared sound effect. You can decide */
/* what volume, which channel, what rate, which priority, how many times */
/* the sound should be played and so on... */
/* */
/* Synopsis: ok = PlaySound( ptr, vol, cha, pri, drate, times, start, */
/* time, wait ); */
/* */
/* ok: (BOOL) If the sound was played successfully TRUE is */
/* returned, else FALSE. */
/* */
/* ptr: (struct SoundInfo *) Pointer to a SoundInfo structure. This */
/* pointer was returned by PrepareSound(). */
/* */
/* vol: (UWORD) Volume, 0 to 64. */
/* */
/* cha: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
/* RIGHT1 or LEFT1) */
/* */
/* pri: (BYTE) What priority should be used. See header file for a */
/* complete list of recommended priorities. */
/* */
/* drate: (WORD) Delta rate. When the sound is prepared, the record */
/* rate is automatically stored in the SoundInfo structure, */
/* so if you do not want to change the rate, write NORMALRATE. */
/* */
/* times: (UWORD) How many times the sound should be played. If you */
/* want to play the sound forever, write NONSTOP. (To stop a */
/* sound call the function StopSound().) */
/* */
/* start: (ULONG) Where in the sound data we should start to play. (If */
/* you want to start at the beginning of the sound data set start */
/* to 0.) */
/* */
/* time: (ULONG) For how long time the sound should be played. If you */
/* want to play all of the sound data set time to 0. */
/* */
/* wait: (BOOL) Set this parameter to WAIT if you want to wait for the */
/* sound to be completed. If you set it to DO_NOT_WAIT, your */
/* program will continue to run while the sound is played. */
/* NOTE! Do not try to play a sound continiously (times set to */
/* NONSTOP) and at the same time set this field to TRUE! The */
/* request will then never be completed and your program will */
/* come to a dead lock!! */
BOOL ESPlaySound (struct SoundInfo *info, UWORD volume, UBYTE channel,
BYTE priority, WORD delta_rate, UWORD times, ULONG start,
ULONG time, BOOL wait) {
/*
* Before we may play the sound, we must make sure that the sound is not
* already being played. We will therefore call the function
* ISStopSound(), in order to stop the sound if it is playing:
*/
ESStopSound (channel);
if (ESPrepareIOA (CLOCK_CONSTANT/info->RecordRate + delta_rate, volume, times, channel, priority, info, start, time)) {
BeginIO (IOA[channel]);
if (wait)
WaitIO (IOA[channel]);
return (TRUE); /* OK! */
}
else
return (FALSE); /* ERROR! */
}
///
/// "ESStopSound"
/* ESStopSound() */
/* ESStopSound() will stop the specified audio channel from continuing */
/* to play the sound. It will also close all devices and ports that */
/* have been opened, and deallocate some memory that have been */
/* allocated. */
/* */
/* Synopsis: ISStopSound( channel ); */
/* channel: (UBYTE) The audio channel that should be stopped. (LEFT0, */
/* LEFT1, RIGHT0 or RIGHT1.) */
void ESStopSound (UBYTE channel)
{
/* Check if the IOAudio structure exist: */
if (IOA[channel]) {
/* 1. Stop the sound: */
AbortIO (IOA[channel]);
/* 2. If there exist a Sound Device, close it: */
if (IOA[channel]->ioa_Request.io_Device)
CloseDevice (IOA[channel]);
/* 3. If there exist a Message Port, delete it: */
if (IOA[channel]->ioa_Request.io_Message.mn_ReplyPort)
DeletePort (IOA[channel]->ioa_Request.io_Message.mn_ReplyPort);
/* 4. Remove the request block: */
DeleteExtIO (IOA[channel], sizeof (struct IOAudio));
/* 5. Set the pointer to NULL so we know that this */
/* request has now been deleted: */
IOA[channel] = NULL;
}
}
///
/// "ESPrepareIOA"
/* ESPrepareIOA() */
/* ESPrepareIOA() allocates and initializes an IOAudio structure. */
/* */
/* Synopsis: ok = ISPrepareIOA( per, vol, cyc, cha, ptr, start, time ); */
/* */
/* ok: (BOOL) If the IOAudio structure was allocated and */
/* initialized successfully, TRUE is returned, else FALSE. */
/* per: (UWORD) Period time. */
/* vol: (UWORD) Volume, 0 to 64. */
/* cyc: (UWORD) How many times the sound should be played. */
/* (0 : forever) */
/* cha: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
/* RIGHT1 or LEFT1) */
/* ptr: (struct SoundInfo *) Pointer to a SoundInfo structure. */
/* start: (ULONG) Where in the sound data we should start to play. */
/* time: (ULONG) For how long time the sound should be played. */
BOOL ESPrepareIOA (UWORD period, UWORD volume, UWORD cycles, UBYTE channel,
BYTE priority, struct SoundInfo *info, ULONG start,
ULONG time)
{
/* Store error numbers here: */
BYTE error;
/* Declare a pointer to a MsgPort structure: */
struct MsgPort *port;
/* Get a reply port: (No name, normal priority) */
port = (struct MsgPort *)
CreatePort (NULL, 0);
/* Did we get a reply port? */
if (!port) {
/* Bad news! We did not get a reply port. */
/* Return with an error value: */
return (FALSE);
}
/* Create an IOAudio request: */
IOA[channel] = (struct IOAudio *)
CreateExtIO (port, sizeof (struct IOAudio));
/* Could we allocate enough memory? */
if (!IOA[channel]) {
/* Tough luck! We did not get a request block. */
/* Close the reply port: */
DeletePort (port);
/* Return with an error value: */
return (FALSE);
}
/* Initialize the IOAudion structure: */
/* Set priority: */
IOA[channel]->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
/* Set channel: (This program tries to reserve one specific */
/* audio channel. It does not support an allocation array */
/* with several options.) */
info->channel_bit = 1 << channel;
/* Give the request block a pointer to our simple allocation array: */
IOA[channel]->ioa_Data = &(info->channel_bit);
/* Set the length of our allocation array: */
IOA[channel]->ioa_Length = sizeof (UBYTE);
/* Open Audio Device: */
error = OpenDevice (AUDIONAME, 0, IOA[channel], 0);
/* Have wee successfully opened it? */
if (error) {
/* Hard times! Could not open the device! */
/* Delete the request block: */
DeleteExtIO (IOA[channel], sizeof (struct IOAudio));
/* Close the reply port: */
DeletePort (port);
/* Set audio pointer to NULL so we know that */
/* we do not have any request block here: */
IOA[channel] = NULL;
/* Return with an error value: */
return (FALSE); /* ERROR! */
}
/* We now have a reply port, a request block, one */
/* audio channel reserved and the audio device has */
/* been opened. Prepare to play: */
/* Initialize the request block with the users requirements: */
IOA[channel]->ioa_Request.io_Flags = ADIOF_PERVOL;
/* We want to play sound (write data to the audio device): */
IOA[channel]->ioa_Request.io_Command = CMD_WRITE;
/* Set period value: */
IOA[channel]->ioa_Period = period;
/* Set volume: */
IOA[channel]->ioa_Volume = volume;
/* Number of times the sound wave should be played: */
IOA[channel]->ioa_Cycles = cycles;
/* If the user has specified a play time we use */
/* it, else we play the complete sound: */
if (time)
IOA[channel]->ioa_Length = time;
else
IOA[channel]->ioa_Length = info->FileLength;
/* Set start position in the waveform: */
IOA[channel]->ioa_Data = info->SoundBuffer + start;
/* Everything has been prepared, return with OK: */
return (TRUE);
}
///
/// "ESRemoveSound"
/* ESRemoveSound() */
/* ESRemoveSound() will stop playing the sound, and deallocate all memory */
/* that was allocated by the PrepareSound() function. Before your program */
/* terminates, all soundeffects that have been prepared, MUST be removed. */
/* */
/* IMPORTANT! Each channel that is currently playing the sound must be */
/* stopped before you may remove the sound!!!! (Use the ESStopSound() */
/* function.) */
/* */
/* Synopsis: ESRemoveSound( pointer ); */
/* */
/* pointer: (struct SoundInfo *) Pointer to a SoundInfo structure. */
void ESRemoveSound (struct SoundInfo *info)
{
/* IMPORTANT! The sound must have been */
/* stopped before you may remove it!!! */
/* Have we allocated a SoundInfo structure? */
if (info) {
/* Deallocate the sound buffer: */
FreeMem (info->SoundBuffer, info->FileLength);
/* Deallocate the SoundInfo structure: */
FreeMem (info, sizeof (struct SoundInfo));
info = NULL;
}
}
///
/// "ESPrepareSound"
/* ESPrepareSound()
ESPrepareSound() loads a sampled sound file (IFF or FutureSound) into a
buffer that is automatically allocated. All information about the sound
(record rate, length, buffersize etc) is put into an SoundInfo structure.
If ESPrepareSound() has successfully prepared the sound it returns a
pointer to a SoundInfo structure, otherwise it returns NULL.
Synopsis: pointer = ESPrepareSound( filename );
pointer: (struct SoundInfo *) Pointer to a SoundInfo structure.
filename: (STRPTR) Pointer to a string containing the name of the
sound file. For example "df0:Explosion.snd".
*/
struct SoundInfo *ESPrepareSound (STRPTR file) {
struct SoundInfo *info;
/*
* Allocate memory for a SoundInfo structure: (The memory can be of
* any type, and should be cleared.)
*/
info = (struct SoundInfo *)AllocMem (sizeof (struct SoundInfo), MEMF_CLEAR);
if (!info) {
return (NULL);
}
/*
* Get the size of the sound file, and store it in the SoundInfo
* structure:
*/
info->FileLength = ESGetSize (file);
if (info->FileLength == 0) {
FreeMem (info, sizeof (struct SoundInfo));
return (NULL);
}
/*
* Allocate enough memory for the sampled sound, and store a pointer to
* the buffer in the SoundInfo structure: (Remember that sound data must
* be in chip memory.)
*/
info->SoundBuffer = (BYTE *) AllocMem (info->FileLength, MEMF_CHIP | MEMF_CLEAR);
if (!info->SoundBuffer) {
FreeMem (info, sizeof (struct SoundInfo));
return (NULL);
}
info->RecordRate = ESLoadSound (file, info);
if (info->RecordRate == 0) {
FreeMem (info->SoundBuffer, info->FileLength);
FreeMem (info, sizeof (struct SoundInfo));
return (NULL);
}
/*
* The sound has now successfully been loaded!
*/
/*
* Old FutureSound files were saved in kHz. If the record rate is less
* than one hundered, we know it is an old FutureSound file, and simply
* multiply the rate with one thousand:
*/
if (info->RecordRate < 100)
info->RecordRate *= 1000;
/* Return a pointer to the SoundInfo structure: */
return (info);
}
///
/// "ESLoadSound"
/* ESLoadSound() */
/* ESLoadSound() will load sampled sound that was either saved in IFF */
/* or FutureSound format. */
/* */
/* Synopsis: rate = ESLoadSound( filename, pointer ); */
/* */
/* rate: (UWORD) The record rate is returned if the sound was */
/* successfully loaded, else 0. */
/* */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
/* */
/* pointer: (struct SoundInfo *) Pointer to a SoundInfo structure. */
UWORD ESLoadSound (STRPTR filename, struct SoundInfo * info)
{
FILE *file_ptr; /* Pointer to a file. */
ULONG length; /* Data Length. */
UWORD record_rate; /* Record rate. */
/* Check if it is an IFF File: */
if (ESSizeIFF (filename)) {
/* Yes, it is an IFF file. Read it: */
return (ESReadIFF (filename, info));
}
else {
/* No, then it is probably a FutureSound file. */
/* Open the file so we can read it: */
if ((file_ptr = fopen (filename, "r")) == 0)
return (0); /* ERROR! Could not open the file! */
/* Read the data length: */
if (fread ((char *) &length, sizeof (ULONG), 1, file_ptr) == 0) {
/* ERROR! Could not read the data length! */
/* Close the file, and return zero: */
fclose (file_ptr);
return (0);
}
/* Read the record rate: */
if (fread ((char *) &record_rate, sizeof (UWORD), 1, file_ptr) == 0) {
/* ERROR! Could not read the record rate! */
/* Close the file, and return zero: */
fclose (file_ptr);
return (0);
}
/* Read the sampled sound data into the buffer: */
if (fread ((char *) info->SoundBuffer, length, 1, file_ptr) == 0) {
/* ERROR! Could not read the data! */
/* Close the file, and return zero: */
fclose (file_ptr);
return (0);
}
/* Close the file: */
fclose (file_ptr);
/* Return the record rate: */
return (record_rate);
}
}
///
/// "ESGetSize"
/* ESGetSize() */
/* ESGetSize() returns the size of the file which was saved in either */
/* IFF or FutureSound format. */
/* */
/* Synopsis: length = ESGetSize( filename ); */
/* */
/* length: (ULONG) Data length. */
/* */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
ULONG ESGetSize (STRPTR filename)
{
FILE *file_ptr; /* Pointer to a file. */
ULONG length; /* Data length. */
/* Check if it is an IFF File: */
if ((length = ESSizeIFF (filename)) == 0) {
/* No, then it is probably a FutureSound file. */
/* Open the file so we can read it: */
if ((file_ptr = fopen (filename, "r")) == 0)
return (0); /* ERROR! Could not open the file! */
/* Read the data length: */
if (fread ((char *) &length, sizeof (ULONG), 1, file_ptr) == 0) {
/* ERROR! Could not read the data length! */
/* Close the file, and return zero: */
fclose (file_ptr);
return (0);
}
/* Close the file: */
fclose (file_ptr);
}
return (length);
}
///
/// "ESSizeIFF"
/* ESSizeIFF() */
/* ESSizeIFF() returns the size of an IFF file, or zero if something */
/* went wrong (for example, It was not an IFF file). */
/* */
/* Synopsis: length = ESSizeIFF( filename ); */
/* */
/* length: (ULONG) Data length. */
/* */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* IFF file. For example "df0:Explosion.snd". */
ULONG ESSizeIFF (STRPTR filename)
{
FILE *file_ptr; /* Pointer to a file. */
STRPTR empty_string = " "; /* Four spaces. */
LONG dummy; /* A dummy variable. */
Voice8Header Header; /* Voice8Header structure. */
/* Try to open the file: */
if (file_ptr = fopen (filename, "r")) {
fread ((char *) empty_string, 4, 1, file_ptr);
if (strcmp (empty_string, "FORM") == 0) {
/* Read twice: */
fread ((char *) empty_string, 4, 1, file_ptr);
fread ((char *) empty_string, 4, 1, file_ptr);
/* Check if it is a "8SVX" file, or not: */
if (strcmp (empty_string, "8SVX") == 0) {
ESMoveTo ("VHDR", file_ptr);
fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
fread ((char *) &Header, sizeof (Header), 1, file_ptr);
/* Close the file, and return the length: */
fclose (file_ptr);
return (Header.oneShotHiSamples + Header.repeatHiSamples);
}
}
/* Close the file: */
fclose (file_ptr);
}
/* Return zero: (ERROR) */
return (0);
}
///
/// "ESReadIFF"
/* ESReadIFF() */
/* ESReadIFF() reads an IFF file into the buffer, and returns the record */
/* rate. */
/* */
/* Synopsis: rate = ESReadIFF( filename, pointer ); */
/* */
/* rate: (UWORD) The record rate is returned if the sound was */
/* successfully loaded, else 0. */
/* */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
/* */
/* pointer: (struct SoundInfo *) Pointer to a SoundInfo structure. */
UWORD ESReadIFF (STRPTR filename, struct SoundInfo * info)
{
FILE *file_ptr; /* Pointer to a file. */
STRPTR empty_string = " "; /* Four spaces. */
LONG dummy; /* A dummy variable. */
Voice8Header Header; /* Voice8Header structure. */
/* Try to open the file: */
if (file_ptr = fopen (filename, "r")) {
fread ((char *) empty_string, 4, 1, file_ptr);
if (strcmp (empty_string, "FORM") == 0) {
/* Read twice: */
fread ((char *) empty_string, 4, 1, file_ptr);
fread ((char *) empty_string, 4, 1, file_ptr);
/* Check if it is a "8SVX" file, or not: */
if (strcmp (empty_string, "8SVX") == 0) {
ESMoveTo ("VHDR", file_ptr);
fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
fread ((char *) &Header, sizeof (Header), 1, file_ptr);
ESMoveTo ("BODY", file_ptr);
fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
fread ((char *) info->SoundBuffer, Header.oneShotHiSamples +
Header.repeatHiSamples, 1, file_ptr);
/* Close the file, and return the record rate: */
fclose (file_ptr);
return (Header.samplesPerSec);
}
}
/* Close the file: */
fclose (file_ptr);
}
/* Return zero: (ERROR) */
return (0);
}
///
/// "ESMoveTo"
/* ESMoveTo() */
/* ESMoveTo() walks through an IFF file, and looks for chunks. */
/* */
/* Synopsis: ESMoveTo( chunk, file_ptr ); */
/* */
/* chunk: (STRPTR) The chunk we want to get to. */
/* */
/* file_ptr: (FILE *) Pointer to an already opened file. */
BOOL ESMoveTo (STRPTR check_string, FILE * file_ptr)
{
STRPTR empty_string = " "; /* Four spaces. */
int skip, loop; /* How much data should be skiped. */
LONG dummy; /* A dummy variable. */
/* As long as we have not reached the EOF, continue: */
while (!feof (file_ptr)) {
fread ((char *) empty_string, 4, 1, file_ptr);
/* Have we found the right chunk? */
if (strcmp (check_string, empty_string) == 0)
return (0); /* YES! Return nothing. */
/* Move foreward: */
fread ((char *) &skip, sizeof (LONG), 1, file_ptr);
for (loop = 0; loop < skip; loop++)
fread ((char *) &dummy, 1, 1, file_ptr);
}
}
///